

--@ enable=true
--@ module=true
local json = require("json")
local persist = require("persist-table")
local argparse = require("argparse")
local repeatutil = require("repeat-util")

local GLOBAL_KEY = "automelt"

enabled = enabled or false
s_mat = s_mat or { 
    copper=true, 
    iron=true, 
    bronze=true, 
    ["bismuth bronze"]=true,
    steel=false,
    silver=false,
    platinum=false,
    ["divine metal"]=false,
    adamantine=false
}
s_quality = s_quality or {
    ["0"]= true,
    ["1"]= true,
    ["2"]= true,
    ["3"]= true,
    ["4"]= true,
    ["5"]= false,
    ["6"]= false,
}

--- Check if the script is enabled.
-- @return true if the script is enabled, otherwise false.
function isEnabled()
    return enabled
end
local function writeFile (str, type, filename) 
    file = io.open("./hack/raw/"..(filename or "tmp"), type)  -- w+ a
    file:write(str)
    file:close()
end
--- Save the current state of the script
local function persist_state()
    persist.GlobalTable[GLOBAL_KEY] = json.encode({
        enabled=enabled,
        s_mat=s_mat, 
        s_quality=s_quality
    })
end
function set_s_mat(val)
    s_mat = val
    persist_state()
end
function set_s_quality(val)
    s_quality = val
    persist_state()
end
--- Load the saved state of the script
local function load_state()
    -- load persistent data
    local persisted_data = json.decode(persist.GlobalTable[GLOBAL_KEY] or "") or {}
    enabled = persisted_data.enabled or false
    s_mat = persisted_data.s_mat or { 
        copper=true, 
        iron=true, 
        bronze=true, 
        ["bismuth bronze"]=true,
        steel=false,
        silver=false,
        platinum=false,
        ["divine metal"]=false,
        adamantine=false
    }
    s_quality = persisted_data.s_quality or {
        ["0"]= true,
        ["1"]= true,
        ["2"]= true,
        ["3"]= true,
        ["4"]= true,
        ["5"]= false,
        ["6"]= false,
    }
end

--- The main event loop of the script.
function event_loop()
    if not enabled then return end
    
    writeFile("automelt"..tostring(enabled).."\n"..json.encode(s_mat)..json.encode(s_quality), "W+", "automelt")
   
    for id, item in ipairs(df.global.world.items.other.IN_PLAY) do
        local flags = item.flags
        if item and not flags.forbid and not flags.trader and not flags.melt and not dfhack.items.getHolderUnit(item) and not flags.dump then
            local ID = df.item_type[item:getType()]
            if ID and dfhack.items.getSubtypeCount(df.item_type[ID]) ~= -1 and item.mat_type then
                local des = dfhack.items.getDescription(item, 0, true)
                local matInfo = dfhack.matinfo.decode(item.mat_type,item.mat_index)
                local matName = matInfo:toString()
                local subTypeId = item.subtype.id
                local quality = item.quality   
                if flags.artifact_mood then 
                    quality = 6
                end
                local subTypeName = string.match(subTypeId, '^ITEM_([^_]*)_')
                if matName == "copper" or matName == "iron" or matName == "bronze" or matName == "silver" or matName == "platinum" or matName == "steel" or matName == "adamantine" or matName == "bismuth bronze" or matName == "divine metal"  then
                    if subTypeName then 
                        if subTypeName =="AMMO" or subTypeName =="SHIELD" or subTypeName =="WEAPON" or subTypeName =="ARMOR" or subTypeName =="HELM" or subTypeName =="GLOVES" or subTypeName =="PANTS" or subTypeName =="SHOES" then
                            if s_mat[matName] and s_quality[tostring(quality)] then
                                if not dfhack.items.getOwner(item) then
                                    -- dfhack.items.setOwner(item)
                                    local meltCount = -1
                                    for i, _ in pairs(df.global.world.items.other.ANY_MELT_DESIGNATED) do
                                        meltCount = meltCount + 1
                                    end
                                    df.global.world.items.other.ANY_MELT_DESIGNATED:insert("#", item)
                                    item.flags.melt = true
                                end
                            end
                        end
                    end
                end
            end
        end
    end

    writeFile("automelt item check end", "W+", "automelt")


    persist_state()

    writeFile("automelt persist_state", "W+", "automelt")

    -- check dayily
    repeatutil.scheduleUnlessAlreadyScheduled(GLOBAL_KEY, 1, "days", event_loop)
end

--- Handles automatic loading
dfhack.onStateChange[GLOBAL_KEY] = function(sc)
    -- unload with game
    if sc == SC_MAP_UNLOADED then
        enabled = false
        return
    end

    if sc ~= SC_MAP_LOADED or df.global.gamemode ~= df.game_mode.DWARF then
        return
    end

    load_state()

    -- run the main code
    event_loop()
end


-- sanity checks?
if dfhack_flags.module then
    return
end

if df.global.gamemode ~= df.game_mode.DWARF or not dfhack.isMapLoaded() then
    dfhack.printerr("automelt needs a loaded fortress to work")
    return
end

-- argument handling
local args = {...}
if dfhack_flags and dfhack_flags.enable then
    args = {dfhack_flags.enable_state and "enable" or "disable"}
end

-- lookup to convert arguments to bool values.
local toBool={["true"]=true,["yes"]=true,["y"]=true,["on"]=true,["1"]=true,
              ["false"]=false,["no"]=false,["n"]=false,["off"]=false,["0"]=false}

local positionals = argparse.processArgsGetopt(args,
    {{"r", "raw", hasArg=true,
    handler=function(optArg)
        optArg=string.lower(optArg)
        if toBool[optArg] ~= nil then
            set_useRaw(toBool[optArg])
        else
            qerror("Invalid argument to --raw \"".. optArg .."\". expected boolean")
        end
    end}
})

load_state()
if positionals[1] == "enable" then
    enabled = true

elseif positionals[1] == "disable" then
    enabled = false
    persist_state()
    repeatutil.cancel(GLOBAL_KEY)
    return
else 
    return
end

event_loop()
persist_state()
